package com.xiaotu.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.xiaotu.constant.RewardPunishEnum;
import com.xiaotu.dto.CalculateIntegralDto;
import com.xiaotu.dto.EndOfGameDto;
import com.xiaotu.mapper.CoordinateMapper;
import com.xiaotu.mapper.LevelRuleMapper;
import com.xiaotu.mapper.PlayerEquipmentMapper;
import com.xiaotu.mapper.PlayerMapper;
import com.xiaotu.model.PlayerEquipmentModel;
import com.xiaotu.model.PlayerModel;
import com.xiaotu.service.LevelRuleService;
import com.xiaotu.util.IntegralUtil;
import com.xiaotu.vo.EndOfGameVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;


/**
 * @author zhangxiao
 * @create 2022-03-25 9:25
 */
@Service
public class LevelRuleServiceImpl implements LevelRuleService {

    @Autowired
    private LevelRuleMapper levelRuleMapper;

    @Autowired
    private PlayerEquipmentMapper playerEquipmentMapper;

    @Autowired
    private PlayerMapper playerMapper;

    @Autowired
    private CoordinateMapper coordinateMapper;

    @Override
    public Object getLevelRule() {
        return levelRuleMapper.selectAll();
    }

    @Transactional
    @Override
    public EndOfGameVo endOfGame(EndOfGameDto end) {
        Example example = new Example(PlayerEquipmentModel.class);
        example.createCriteria().andEqualTo("playerId", end.getSelfPlayerId());
        example.selectProperties("goldCoins");
        Integer historyGoldCoins = playerEquipmentMapper.selectOneByExample(example).getGoldCoins();
        //校验当前是否走棋部数<=1
        Integer maxStep = coordinateMapper.getMaxStep(end.getSelfPlayerId(), end.getRoomId());
        if (ObjectUtil.isNull(maxStep) || maxStep <= 1)
            return new EndOfGameVo(0, 0, 0, null, historyGoldCoins);
        //增加红包奖励
        PlayerEquipmentModel equipment = new PlayerEquipmentModel();
        equipment.setPlayerId(end.getSelfPlayerId());
        Integer goldCoins = Math.multiplyExact(RewardPunishEnum.RED_PACKET_GOLD_COINS_BASE.getVal(), Integer.valueOf(end.getRedPacket()));
        //计算积分涨浮
        CalculateIntegralDto ca = calculateIntegral(end.getSelfPlayerId(), end.getGameResult(), end.isFirstHand(), end.getOtherPlayerId(), end.getSelfCalculate(), end.getOtherCalculate());
        EndOfGameVo endOfGameVo = new EndOfGameVo();
        if (end.getGameResult() != 1D) {
            endOfGameVo.setGoldCoinsRewardPunish(~(RewardPunishEnum.GOLD_COINS.getVal() - 1));
        } else {
            endOfGameVo.setGoldCoinsRewardPunish(RewardPunishEnum.GOLD_COINS.getVal());
        }
        endOfGameVo.setRedPacketReward(goldCoins);
        endOfGameVo.setExperienceRewardPunish(ca.getIntegralRiseFall());
        //将红包数与奖惩金币 计算汇总
        Integer finalGoldCoins = Math.addExact(Math.addExact(goldCoins, historyGoldCoins), endOfGameVo.getGoldCoinsRewardPunish());
        endOfGameVo.setGoldCoins(finalGoldCoins);
        equipment.setGoldCoins(finalGoldCoins < 0 ? 0 : finalGoldCoins);
        equipment.setCalculate(ca.getNews() < 0 ? 0 : ca.getNews());
        playerEquipmentMapper.updateByPrimaryKeySelective(equipment);
        //更新等级
        PlayerModel player = new PlayerModel();
        player.setPlayerId(end.getSelfPlayerId());
        player.setLevel(IntegralUtil.levelVal(ca.getNews()));
        Example levelExample = new Example(PlayerModel.class);
        levelExample.createCriteria().andEqualTo("playerId", end.getSelfPlayerId());
        levelExample.selectProperties("level");
        Integer oldLevel = playerMapper.selectOneByExample(levelExample).getLevel();
        endOfGameVo.setUpgradeLevel(player.getLevel().compareTo(oldLevel) > 0 ? player.getLevel() : null);
        playerMapper.updateByPrimaryKeySelective(player);
        return endOfGameVo;
    }

    /**
     * 计算积分
     *
     * @param selfPlayerId   本人的玩家ID
     * @param gameResult     为对局结果 ( 胜为 1 负为 0 和为 0.5)
     * @param isFirstHand    是否是先手
     * @param otherPlayerId  对方玩家ID
     * @param selfCalculate  本玩家旧积分
     * @param otherCalculate 对方旧积分
     */
    @Override
    public CalculateIntegralDto calculateIntegral(Integer selfPlayerId, Double gameResult, boolean isFirstHand, Integer otherPlayerId, Integer selfCalculate, Integer otherCalculate) {
        CalculateIntegralDto ca = new CalculateIntegralDto();
        ca.setPlayerId(selfPlayerId);
        ca.setOlds(selfCalculate);
        ca.setK(IntegralUtil.kVal(selfCalculate));
        ca.setRes(gameResult);
        if (isFirstHand) {
            ca.setYFirst(~(RewardPunishEnum.IS_FIRST_HAND.getVal() - 1));
        } else {
            ca.setYFirst(RewardPunishEnum.IS_FIRST_HAND.getVal());
        }
        ca.setSelfCalculate(selfCalculate);
        ca.setOtherCalculate(otherCalculate);
        ca.setExp(ca.getCalculateExp());
        ca.setNews(ca.getCalculateNews());
        ca.invokeIntegralRiseFall();
        return ca;
    }

}
